function forecastLayout(cache, dataList) {
    let data = cache.data;
    let children = [];

    for (var i = 0; i < dataList.length; i++) {
        if (isParent(data, dataList[i])) {
            let child = getCache(dataList[i]);
            if (!child.parent && cache.index < child.index) {
                children.push(dataList[i]);
            }
        }
    }

    return autoLayout(cache, children);
}

function autoLayout(cache, children) {
    for (let i = 0; i < children.length; i++) {
        let a = children[i];
        let aCache = getCache(a);
        let parent = findParent(aCache, children);
        if (parent && cache != parent) {
            setupLevel(parent, a);
        }
    }

    children = children.filter(function (item) {
        let cache = getCache(item);
        let type = figure(item);
        let hasChildren = (cache.children && cache.children.length > 0) || false;
        let isGroup = type == "SizedBox" && hasChildren;
        return (!cache.parent && type != "SizedBox") || isGroup;
    });

    return smartLayout(children);
}

function smartLayout(children) {
    for (let i = 0; i < children.length; i++) {
        let a = children[i];
        let aCache = getCache(a);
        aCache.xInsect = 0;
        aCache.yInsect = 0;
    }

    for (let i = 0; i < children.length; i++) {
        for (let j = i + 1; j < children.length; j++) {
            let a = children[i];
            let b = children[j];

            let aCache = getCache(a);
            let bCache = getCache(b);
            if ((a.x >= b.x && a.x < b.x + b.width) || (b.x >= a.x && b.x < a.x + a.width)) {
                aCache.xInsect++;
                bCache.xInsect++;
            }

            if (a.y >= b.y && a.y < b.y + b.height || b.y >= a.y && b.y < a.y + a.height) {
                aCache.yInsect++;
                bCache.yInsect++;
            }
        }
    }

    let row = 0;
    let column = 0;
    for (let i = 0; i < children.length; i++) {
        let a = children[i];
        let aCache = getCache(a);
        if (!aCache.xInsect) {
            row++;
        }

        if (!aCache.yInsect) {
            column++;
        }
    }

    if (row > column) {
        return setupRow(children);
    } else if (column > row) {
        return setupColumn(children);
    } else {
        return newVirtual();
    }
}

function setupRow(children) {
    children.sort((a, b) => a.x - b.x);

    let row = newVirtual();
    let nextGroup = [];
    let lastY = children[0].y;
    let last = children[0];
    for (let i = 0; i < children.length; i++) {
        let a = children[i];
        let aCache = getCache(a);
        if (lastY > a.y) {
            let intersect = (a.x >= last.x && a.x < last.x + last.width) || (last.x >= a.x && last.x < a.x + a.width);
            if (nextGroup.length > 0 && !intersect) {
                let group = smartLayout(nextGroup);
                setupLevel(row.data, group.data);
                nextGroup.length = 0;
            }
            if (!aCache.xInsect) {
                setupLevel(row.data, a);
            } else {
                nextGroup.push(a);
            }
        } else if (!aCache.xInsect) {
            if (nextGroup.length > 0) {
                let group = smartLayout(nextGroup);
                setupLevel(row.data, group.data);
                nextGroup.length = 0;
            }
            setupLevel(row.data, a);
        } else {
            nextGroup.push(a);
        }
        last = a;
        lastY = a.y + a.height;
    }

    if (nextGroup.length > 0) {
        let group = smartLayout(nextGroup);
        setupLevel(row.data, group.data);
    }

    let childDatas = row.children.map(function (item) {
        return item.data
    })
    fixLayoutSize(row);
    row.type = supposeLayout(childDatas);
    return row;
}

function setupColumn(children) {
    children.sort((a, b) => a.y - b.y);

    let column = newVirtual();
    let nextGroup = [];
    let lastX = children[0].x;
    let last = children[0];
    for (let i = 0; i < children.length; i++) {
        let a = children[i];
        let aCache = getCache(a);
        if (lastX > a.x) {
            let intersect = (a.y >= last.y && a.y < last.y + last.height) || (last.y >= a.y && last.y < a.y + a.height);

            if (nextGroup.length > 0 && !intersect) {
                let group = smartLayout(nextGroup);
                setupLevel(column.data, group.data);
                nextGroup.length = 0;
            }
            if (!aCache.yInsect) {
                setupLevel(column.data, a);
            } else {
                nextGroup.push(a);
            }
        } else if (!aCache.yInsect) {
            if (nextGroup.length > 0) {
                let group = smartLayout(nextGroup);
                setupLevel(column.data, group.data);
                nextGroup.length = 0;
            }
            setupLevel(column.data, a);
        } else {
            nextGroup.push(a);
        }
        lastX = a.x + a.width;
        last = a;
    }
    if (nextGroup.length > 0) {
        let group = smartLayout(nextGroup);
        setupLevel(column.data, group.data);
    }

    let childDatas = column.children.map(function (item) {
        return item.data
    })
    fixLayoutSize(column);
    column.type = supposeLayout(childDatas);

    return column;
}